﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using Cleverscape.UTorrentClient.WebClient;
using GalaSoft.MvvmLight.Threading;

namespace Cleverscape.UTorrentClient.WebClient
{
    /// <summary>
    /// Represents a Feed currently active within uTorrent
    /// </summary>
    public class Filter : INotifyPropertyChanged
    {

        #region Private Fields


        internal FilterCollection ParentCollection;
        //private FeedItemCollection _feedItems;

        private int _ident;
        private int _flags
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                sb.Append((_DontStartAuto) ? "1" : "0");
                sb.Append((_SmartEpFilter) ? "1" : "0");
                sb.Append((_GiveHighestPrio) ? "1" : "0");
                sb.Append((_FilterMatchesOriginalName) ? "1" : "0");
                sb.Append((_Enabled) ? "1" : "0");
                return Convert.ToByte(sb.ToString().PadLeft(5, '0'), 2);
            }
            set
            {
                string bits = Convert.ToString(value, 2).PadLeft(5, '0');
                bool dsa = (bits[0] == '1') ? true : false;
                if (DontStartAuto != dsa)
                    DontStartAuto = dsa;
                bool sef = (bits[1] == '1') ? true : false;
                if (SmartEpFilter != sef)
                    SmartEpFilter = sef;
                bool ghp = (bits[2] == '1') ? true : false;
                if (GiveHighestPrio != ghp)
                    GiveHighestPrio = ghp;
                bool fmo = (bits[3] == '1') ? true : false;
                if (FilterMatchesOriginalName != fmo)
                    FilterMatchesOriginalName = fmo;
                bool ena = (bits[4] == '1') ? true : false;
                if (Enabled != ena)
                    Enabled = ena;
            }
        }
        private bool _FilterMatchesOriginalName;
        private bool _DontStartAuto;
        private bool _GiveHighestPrio;
        private bool _SmartEpFilter;
        private bool _Enabled;
        private string _name;
        private string _filter;
        private string _notFilter;
        private string _directory;
        private int _feedId;
        private string _label;
        private int _lastMatch;
        private int _smartEpFilter;
        private int _repackEpFilter;
        private string _episodeFilterStr;
        private bool _episodeFilter;
        private bool _resolvingCanidate;

        #endregion

        #region Constructor

        internal Filter(object[] InputValues, FilterCollection ParentCollection)
        {
            this.ParentCollection = ParentCollection;
            UpdateValuesFromStringArray(InputValues, true);
        }
        public Filter()
        {
            this.Name = "Test Filter";
            this.FilterText = "*everything*";
        }

        internal bool UpdateValuesFromStringArray(object[] InputValues)
        {
            return UpdateValuesFromStringArray(InputValues, false);
        }

        private bool UpdateValuesFromStringArray(object[] InputValues, bool NewFeed)
        {
            bool ReturnChanged = false;
            //bool CallFinishedDownloading = false;
            //bool CallStarted = false;
            //bool CallStopped = false;
            //bool CallPaused = false;
            //bool CallUnPaused = false;
            if (InputValues.Length != 16)
            {
                throw new FormatException("The array of filter data was not in the expected format.");
            }
            if (Ident != Convert.ToInt32(InputValues[0]))
            {
                Ident = Convert.ToInt32(InputValues[0]);
                ReturnChanged = true;
            }
            
            
            if(_flags != Convert.ToInt32(InputValues[1]))
            {
                _flags = Convert.ToInt32(InputValues[1]);
                ReturnChanged = true;
            }
            if (Name != (string)InputValues[2])
            {
                Name = (string)InputValues[2];
                ReturnChanged = true;
            }
            if (FilterText != (string)InputValues[3])
            {
                FilterText = (string)InputValues[3];
                ReturnChanged = true;
            }
            if (NotFilter != (string)InputValues[4])
            {
                NotFilter = (string)InputValues[4];
                ReturnChanged = true;
            }
            if (Directory != (string)InputValues[5])
            {
                Directory = (string)InputValues[5];
                ReturnChanged = true;
            }
            if (Feed != Convert.ToInt32(InputValues[6]))
            {
                Feed = Convert.ToInt32(InputValues[6]);
                ReturnChanged = true;
            }
            if (Quality.QInt != Convert.ToInt32(InputValues[7]))
            {
                Quality.QInt = Convert.ToInt32(InputValues[7]);
                ReturnChanged = true;
            }
            if (Label != (string)InputValues[8])
            {
                Label = (string)InputValues[8];
                ReturnChanged = true;
            }
            if (PostponeMode != (PostponeInterval)Convert.ToInt32(InputValues[9]))
            {
                PostponeMode = (PostponeInterval)Convert.ToInt32(InputValues[9]);
                ReturnChanged = true;
            }
            if (LastMatch != Convert.ToInt32(InputValues[10]))
            {
                LastMatch = Convert.ToInt32(InputValues[10]);
                ReturnChanged = true;
            }
            if (UnknownSmartEpFilter != Convert.ToInt32(InputValues[11]))
            {
                UnknownSmartEpFilter = Convert.ToInt32(InputValues[11]);
                ReturnChanged = true;
            }
            if (RepackEpFilter != Convert.ToInt32(InputValues[12]))
            {
                RepackEpFilter = Convert.ToInt32(InputValues[12]);
                ReturnChanged = true;
            }
            if (EpisodeFilterStr != (string)InputValues[13])
            {
                EpisodeFilterStr = (string)InputValues[13];
                ReturnChanged = true;
            }
            if (EpisodeFilter != Convert.ToBoolean(InputValues[14]))
            {
                EpisodeFilter = Convert.ToBoolean(InputValues[14]);
                ReturnChanged = true;
            }
            if (ResolvingCandidate != Convert.ToBoolean(InputValues[15]))
            {
                ResolvingCandidate = Convert.ToBoolean(InputValues[15]);
                ReturnChanged = true;
            }
            
            
           
            //if (CallFinishedDownloading)
            //{
            //    ParentCollection.ParentClient.CallEvent(UTorrentWebClient.EventType.FinishedDownloading, this);
            //}
            //if (CallPaused)
            //{
            //    ParentCollection.ParentClient.CallEvent(UTorrentWebClient.EventType.Paused, this);
            //}
            //if (CallUnPaused)
            //{
            //    ParentCollection.ParentClient.CallEvent(UTorrentWebClient.EventType.UnPaused, this);
            //}
            //if (CallStarted)
            //{
            //    ParentCollection.ParentClient.CallEvent(UTorrentWebClient.EventType.Started, this);
            //}
            //if (CallStopped)
            //{
            //    ParentCollection.ParentClient.CallEvent(UTorrentWebClient.EventType.Stopped, this);
            //}
            return ReturnChanged;
        }

        

        #endregion

        #region Public Methods (Overriden from object)

        public override bool Equals(object obj)
        {
            return (obj is Filter) && ((Filter)obj).Ident == this.Ident;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        

        #endregion

        #region Public Events (INotifyPropertyChanged)

        /// <summary>
        /// Event to notify when a property of the torrent has changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string PropertyName)
        {
            if (DispatcherHelper.UIDispatcher != null)
            {
                DispatcherHelper.UIDispatcher.BeginInvoke(() =>
                {
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
                    }
                });
            }
            else
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
                }
            }
        }

        #endregion

        

        

        #region Public Properties (Basic Torrent Properties)

        
        public int Ident
        {
            get
            {
                return _ident;
            }
            private set
            {
                _ident = value;
                NotifyPropertyChanged("Ident");
            }
        }

        public bool Enabled
        {
            get
            {
                return _Enabled;
            }
            //No way to enable or disable in the update command
            private set
            {
                _Enabled = value;
                NotifyPropertyChanged("Enabled");
            }
        }

        public bool FilterMatchesOriginalName
        {
            get
            {
                return _FilterMatchesOriginalName;
            }
            set
            {
                _FilterMatchesOriginalName = value;
                NotifyPropertyChanged("FilterMatchesOriginalName");
            }
        }

        public bool DontStartAuto
        {
            get
            {
                return _DontStartAuto;
            }
            set
            {
                _DontStartAuto = value;
                NotifyPropertyChanged("DontStartAuto");
            }
        }

        public bool GiveHighestPrio
        {
            get
            {
                return _GiveHighestPrio;
            }
            set
            {
                _GiveHighestPrio = value;
                NotifyPropertyChanged("GiveHighestPrio");
            }
        }

        public bool SmartEpFilter
        {
            get
            {
                return _SmartEpFilter;
            }
            set
            {
                _SmartEpFilter = value;
                NotifyPropertyChanged("SmartEpFilter");
            }
        }

        public string Name
        {
            get
            {
                return _name;
            }
            set
            {
                _name = value;
                NotifyPropertyChanged("Name");
            }
        }
        public string FilterText
        {
            get
            {
                return _filter;
            }
            set
            {
                _filter = value;
                NotifyPropertyChanged("FilterText");
            }
        }
        public string NotFilter
        {
            get
            {
                return _notFilter;
            }
            set
            {
                _notFilter = value;
                NotifyPropertyChanged("NotFilter");
            }
        }

        public string Directory
        {
            get
            {
                return _directory;
            }
            private set
            {
                _directory = value;
                NotifyPropertyChanged("Directory");
            }
        }

        public int Feed
        {
            get
            {
                return _feedId;
            }
            set
            {
                _feedId = value;
                NotifyPropertyChanged("Feed");
            }
        }

        private Quality pQuality;
        public Quality Quality
        {
            get
            {
                if (pQuality == null)
                    pQuality = new Quality();
                return pQuality;
            }
            private set
            {
                pQuality = value;
                NotifyPropertyChanged("Quality");
            }
        }

        public string Label
        {
            get
            {
                return _label;
            }
            set
            {
                _label = value;
                NotifyPropertyChanged("Label");
            }
        }

        private PostponeInterval _postponeMode = PostponeInterval.MatchAlways;
        public PostponeInterval PostponeMode
        {
            get
            {
                return _postponeMode;
            }
            set
            {
                _postponeMode = value;
                NotifyPropertyChanged("PostponeMode");
            }
        }
        public int LastMatch
        {
            get
            {
                return _lastMatch;
            }
            private set
            {
                _lastMatch = value;
                NotifyPropertyChanged("LastMatch");
            }
        }
        public int UnknownSmartEpFilter
        {
            get
            {
                return _smartEpFilter;
            }
            private set
            {
                _smartEpFilter = value;
                NotifyPropertyChanged("SmartEpFilter");
            }
        }
        public int RepackEpFilter
        {
            get
            {
                return _repackEpFilter;
            }
            private set
            {
                _repackEpFilter = value;
                NotifyPropertyChanged("RepackEpFilter");
            }
        }

        public string EpisodeFilterStr
        {
            get
            {
                return _episodeFilterStr;
            }
            set
            {
                _episodeFilterStr = value;
                NotifyPropertyChanged("EpisodeFilterStr");
            }
        }
        public bool EpisodeFilter
        {
            get
            {
                return _episodeFilter;
            }
            set
            {
                _episodeFilter = value;
                NotifyPropertyChanged("EpisodeFilter");
            }
        }
        public bool ResolvingCandidate
        {
            get
            {
                return _resolvingCanidate;
            }
            private set
            {
                _resolvingCanidate = value;
                NotifyPropertyChanged("ResolvingCandidate");
            }
        }

        #endregion


        #region Public Methods 

        

        /// <summary>
        /// Remove the torrent
        /// </summary>
        /// <param name="RemoveData">Whether or not to remove the data downloaded</param>
        public void Remove()
        {
            ParentCollection.ParentClient.FilterRemove(this);
        }

        public void Update()
        {
            ParentCollection.ParentClient.FilterUpdateAdd(this);
        }

        #endregion

        
        
    }

    public enum PostponeInterval
    {
        MatchAlways = 0,
        MatchOnlyOnce = 1,
        TweleveHours = 2,
        OneSay = 3,
        TwoDays = 4,
        ThreeDays = 5,
        FourDays = 6,
        OneWeek = 7,
        TwoWeeks = 8,
        ThreeWeeks = 9,
        OneMonth = 10
    }
    

    public class Quality : INotifyPropertyChanged
    {
        private bool _DSRip;
        public bool DSRip 
        {
            get
            {
                return _DSRip;     
            }
            set
            {
                bool oldVal = _DSRip;
                _DSRip = value;
                if(oldVal != _DSRip)
                    NotifyPropertyChanged("DSRip");
            }
        }
        private bool _DVBRip;
        public bool DVBRip
        {
            get
            {
                return _DVBRip;
            }
            set
            {
                bool oldVal = _DVBRip;
                _DVBRip = value;
                if (oldVal != _DVBRip)
                    NotifyPropertyChanged("DVBRip");
            }
        }
        private bool _DVDR;
        public bool DVDR
        {
            get
            {
                return _DVDR;
            }
            set
            {
                bool oldVal = _DVDR;
                _DVDR = value;
                if (oldVal != _DVDR)
                    NotifyPropertyChanged("DVDR");
            }
        }
        private bool _DVDRip;
        public bool DVDRip
        {
            get
            {
                return _DVDRip;
            }
            set
            {
                bool oldVal = _DVDRip;
                _DVDRip = value;
                if (oldVal != _DVDRip)
                    NotifyPropertyChanged("DVDRip");
            }
        }
        private bool _DVDScr;
        public bool DVDScr
        {
            get
            {
                return _DVDScr;
            }
            set
            {
                bool oldVal = _DVDScr;
                _DVDScr = value;
                if (oldVal != _DVDScr)
                    NotifyPropertyChanged("DVDScr");
            }
        }
        private bool _HDTV;
        public bool HDTV
        {
            get
            {
                return _HDTV;
            }
            set
            {
                bool oldVal = _HDTV;
                _HDTV = value;
                if (oldVal != _HDTV)
                    NotifyPropertyChanged("HDTV");
            }
        }
        private bool _HRHDTV;
        public bool HRHDTV
        {
            get
            {
                return _HRHDTV;
            }
            set
            {
                bool oldVal = _HRHDTV;
                _HRHDTV = value;
                if (oldVal != _HRHDTV)
                    NotifyPropertyChanged("HRHDTV");
            }
        }
        private bool _HRPDTV;
        public bool HRPDTV
        {
            get
            {
                return _HRPDTV;
            }
            set
            {
                bool oldVal = _HRPDTV;
                _HRPDTV = value;
                if (oldVal != _HRPDTV)
                    NotifyPropertyChanged("HRPDTV");
            }
        }
        private bool _PDTV;
        public bool PDTV
        {
            get
            {
                return _PDTV;
            }
            set
            {
                bool oldVal = _PDTV;
                _PDTV = value;
                if (oldVal != _PDTV)
                    NotifyPropertyChanged("PDTV");
            }
        }
        private bool _SatRip;
        public bool SatRip
        {
            get
            {
                return _SatRip;
            }
            set
            {
                bool oldVal = _SatRip;
                _SatRip = value;
                if (oldVal != _SatRip)
                    NotifyPropertyChanged("SatRip");
            }
        }
        private bool _SVCD;
        public bool SVCD
        {
            get
            {
                return _SVCD;
            }
            set
            {
                bool oldVal = _SVCD;
                _SVCD = value;
                if (oldVal != _SVCD)
                    NotifyPropertyChanged("SVCD");
            }
        }
        private bool _TVRip;
        public bool TVRip
        {
            get
            {
                return _TVRip;
            }
            set
            {
                bool oldVal = _TVRip;
                _TVRip = value;
                if (oldVal != _TVRip)
                    NotifyPropertyChanged("TVRip");
            }
        }
        private bool _WebRip;
        public bool WebRip
        {
            get
            {
                return _WebRip;
            }
            set
            {
                bool oldVal = _WebRip;
                _WebRip = value;
                if (oldVal != _WebRip)
                    NotifyPropertyChanged("WebRip");
            }
        }
        private bool _Seven20p;
        public bool Seven20p
        {
            get
            {
                return _Seven20p;
            }
            set
            {
                bool oldVal = _Seven20p;
                _Seven20p = value;
                if (oldVal != _Seven20p)
                    NotifyPropertyChanged("Seven20p");
            }
        }
        private bool _Ten80i;
        public bool Ten80i
        {
            get
            {
                return _Ten80i;
            }
            set
            {
                bool oldVal = _Ten80i;
                _Ten80i = value;
                if (oldVal != _Ten80i)
                    NotifyPropertyChanged("Ten80i");
            }
        }
        private bool _Ten80p;
        public bool Ten80p
        {
            get
            {
                return _Ten80p;
            }
            set
            {
                bool oldVal = _Ten80p;
                _Ten80p = value;
                if (oldVal != _Ten80p)
                    NotifyPropertyChanged("Ten80p");
            }
        }
        public Quality() { }
        public Quality(int qualityVal) 
        {
            QInt = qualityVal;
        }

        public int QInt
        {
            get
            {
                StringBuilder sb = new StringBuilder();
                sb.Append((SatRip) ? "1" : "0");
                sb.Append((WebRip) ? "1" : "0");
                sb.Append((Ten80p) ? "1" : "0");
                sb.Append((Ten80i) ? "1" : "0");
                sb.Append((Seven20p) ? "1" : "0");
                sb.Append((DVDScr) ? "1" : "0");
                sb.Append((DVDR) ? "1" : "0");
                sb.Append((HRPDTV) ? "1" : "0");
                sb.Append((HRHDTV) ? "1" : "0");
                sb.Append((PDTV) ? "1" : "0");
                sb.Append((DVBRip) ? "1" : "0");
                sb.Append((DSRip) ? "1" : "0");
                sb.Append((SVCD) ? "1" : "0");
                sb.Append((DVDRip) ? "1" : "0");
                sb.Append((TVRip) ? "1" : "0");
                sb.Append((HDTV) ? "1" : "0");
                return Convert.ToInt32(sb.ToString().PadLeft(16, '0'), 2);
            }
            set
            {
                string bits = Convert.ToString(value, 2).PadLeft(16, '0');
                SatRip = (bits[0] == '1') ? true : false;
                WebRip = (bits[1] == '1') ? true : false;
                Ten80p = (bits[2] == '1') ? true : false;
                Ten80i = (bits[3] == '1') ? true : false;
                Seven20p = (bits[4] == '1') ? true : false;
                DVDScr = (bits[5] == '1') ? true : false;
                DVDR = (bits[6] == '1') ? true : false;
                HRPDTV = (bits[7] == '1') ? true : false;
                HRHDTV = (bits[8] == '1') ? true : false;
                PDTV = (bits[9] == '1') ? true : false;
                DVBRip = (bits[10] == '1') ? true : false;
                DSRip = (bits[11] == '1') ? true : false;
                SVCD = (bits[12] == '1') ? true : false;
                DVDRip = (bits[13] == '1') ? true : false;
                TVRip = (bits[14] == '1') ? true : false;
                HDTV = (bits[15] == '1') ? true : false;
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string PropertyName)
        {
            DispatcherHelper.UIDispatcher.BeginInvoke(() =>
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
                }
            });
        }

        #endregion
    }
 
}
